package com.axxc.cloud.common.config;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

@Configuration("druidDbConfigCommon")
@ConditionalOnMissingBean(name = "druidDbConfig")
public class DruidDbConfig {
	private Logger logger = LoggerFactory.getLogger(DruidDbConfig.class);

	@Value("${spring.datasource.url}")
	private String dbUrl;

	@Value("${spring.datasource.username}")
	private String userName;

	@Value("${spring.datasource.password}")
	private String passWord;

	@Value("${spring.datasource.driverClassName}")
	private String driverClassName;

	@Value("${spring.datasource.initialSize}")
	private int initialSize;

	@Value("${spring.datasource.minIdle}")
	private int minIdle;

	@Value("${spring.datasource.maxActive}")
	private int maxActive;

	@Value("${spring.datasource.maxWait}")
	private int maxWait;

	@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
	private int timeBetweenEvictionRunsMillis;

	@Value("${spring.datasource.minEvictableIdleTimeMillis}")
	private int minEvictableIdleTimeMillis;

	@Value("${spring.datasource.validationQuery}")
	private String validationQuery;

	@Value("${spring.datasource.testWhileIdle}")
	private boolean testWhileIdle;

	@Value("${spring.datasource.testOnBorrow}")
	private boolean testOnBorrow;

	@Value("${spring.datasource.testOnReturn}")
	private boolean testOnReturn;

	@Value("${spring.datasource.poolPreparedStatements}")
	private boolean poolPreparedStatements;

	@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
	private int maxPoolPreparedStatementPerConnectionSize;

	@Value("${spring.datasource.filters}")
	private String filters;

	@Value("{spring.datasource.connectionProperties}")
	private String connectionProperties;

	@Primary
	@Bean
	public DataSource dataSource(@Qualifier("wall-filter") WallFilter wallFilter) {
		DruidDataSource datasource = new DruidDataSource();

		datasource.setUrl(this.dbUrl);
		datasource.setUsername(userName);
		datasource.setPassword(passWord);
		datasource.setDriverClassName(driverClassName);

		datasource.setInitialSize(initialSize);
		datasource.setMinIdle(minIdle);
		datasource.setMaxActive(maxActive);
		datasource.setMaxWait(maxWait);
		datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
		datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
		datasource.setValidationQuery(validationQuery);
		datasource.setTestWhileIdle(testWhileIdle);
		datasource.setTestOnBorrow(testOnBorrow);
		datasource.setTestOnReturn(testOnReturn);
		datasource.setPoolPreparedStatements(poolPreparedStatements);
		datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
		/** 关闭自动提交 */
		datasource.setDefaultAutoCommit(false);
		try {
			List<Filter> list = new ArrayList<>();
			list.add(wallFilter);
			datasource.setProxyFilters(list);
			datasource.init();
		} catch (SQLException e) {
			logger.error("dataSource setFilters(filters error ", e);
			System.exit(-1);
		}
		datasource.setConnectionProperties(connectionProperties);
		logger.info("dataSource init");
		return datasource;
	}

	@Bean("wall-filter-config")
	public WallConfig createWallConfig() {
		WallConfig cg = new WallConfig();
		cg.setDir("META-INF/druid/wall/mysql");
		cg.setDeleteWhereNoneCheck(true);
		cg.setUpdateWhereNoneCheck(true);
		cg.setCommentAllow(true);
		cg.setStrictSyntaxCheck(false);
		cg.setTruncateAllow(false);
		cg.setCreateTableAllow(false);
		cg.setAlterTableAllow(false);
		cg.setDropTableAllow(false);
		cg.init();

		return cg;
	}

	@Bean("wall-filter")
	public WallFilter createWallFilter(@Qualifier("wall-filter-config") WallConfig config) {
		WallFilter wallFilter = new WallFilter();
		wallFilter.setDbType(JdbcConstants.MYSQL);
		wallFilter.setConfig(config);
		wallFilter.setLogViolation(true);
		wallFilter.setThrowException(true);
		return wallFilter;
	}

}